NBA球员薪资分析——基于随机森林算法(一)
本文作者:宋 骁
文字编辑:钱梦璇
本文是一个使用机器学习方法预测球员薪资的尝试。由于球员伤病等原因,一些球员的薪资变动非常大,因此我们选用2016-2017赛季的技术统计去预测下一个赛季球员的薪资,这样能够保证球员的竞技状态改变较少。 本文使用的两个数据均来自数据科学平台Kaggle,公开数据源在此: https://www.kaggle.com/koki25ando/salary https://www.kaggle.com/drgilermo/nba-players-stats 其中,变量字段说明如下:
目录
1 数据清理
1.1 变量相关系数
2 变量转换
3 建模
3.1 交叉验证
3.2 变量重要性统计
数据清洗
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
salarydf = pd.read_csv("./data/NBA_season1718_salary.csv")
seasons = pd.read_csv("./data/Seasons_Stats.csv")
salarydf[salarydf['Player'] == 'Troy Williams']
一个赛季辗转两只球队的Troy Williams出现了单独的TOT行:
seasons[(seasons['Player'] == 'Troy Williams') & (seasons['Year'] == 2017)]
因此,如果一个球员辗转多支球队则取他薪资的平均数。这里使用groupby函数计算每一名球员2017-2018赛季的薪资平均数。
salary_mean = salarydf.groupby(salarydf['Player']).mean() # 以球员为分组进行平均
salary_mean = pd.DataFrame(salary_mean)
salary_mean['Player'] = salary_mean.index # 新建球员姓名列
salary_mean.reset_index(drop=True,inplace =True) # 去除 index
salary_mean = salary_mean[['Player','season17_18']] # 选择两列
salary_mean.rename(columns = {'season17_18':'salary17_18'},inplace = True) # 重命名
salary_mean['salary17_18'] = salary_mean['salary17_18'] / 1000000 # 将薪资单位化为百万
salary_mean.head()
对于技术统计数据,采取相同的措施。这里我们将TOT行单独拿出来并删除在单个队伍中的数据统计(TOT记录了汇总值),因为没有TOT行的不属于单赛季辗转过多支球队的球员。
在建模之前我们将会删除模型中不需要的特征,比如说球员姓名等等。同时将汇总数据除以出场次数计算得到场均数据。
seasons = seasons[seasons['Year'] == 2017] # 只保留16-17赛季的技术统计
seasons_tot = seasons[seasons['Tm'] == 'TOT'] # 得到辗转多队的数据行
seasons.drop_duplicates(['Player'], keep= False ,inplace=True) # 删除单个队的数据行
together = pd.concat([seasons, seasons_tot])
together = together[['Player','Pos','Age','G','PER',
'MP','PTS','AST','TRB','TOV','BLK','STL']]
c = ['MPG','PPG','APG','RPG','TOPG','BPG','SPG']
w = ['MP','PTS','AST','TRB','TOV','BLK','STL']
for i,s in zip(c,w): # 把所有汇总数据除以出场次数得到场均值
together[i] = together[s] / together['G']
together.drop(w,axis=1,inplace = True)
together.drop(['G'],axis=1,inplace = True)
together.loc[together['Pos'] == 'PF-C','Pos'] = 'PF' # 重编码
stats_salary = pd.merge(together, salary_mean) # 数据合并
stats_salary.head()
OK!上面就是我们得到的将球员的数据统计和薪资合并以后的数据了。Player对应的是球员姓名,salary17_18对应的是球员2017-2018赛季的薪资(单位:百万美元)。我们后面所要做的是用数据统计特征预测salary17_18这一列。我们可以先画图探查一下各变量之间的线性相关关系。
变量相关系数
%matplotlib inline
%config InlineBackend.figure_format = 'svg' #Jupyter Notebook魔术命令,设置图片输出格式为svg
import seaborn as sns
sns.set_style('white')
plt.rcParams['font.sans-serif']=['SimHei'] # 图片中文输出
plt.rcParams['axes.unicode_minus']=False
heat_salary = stats_salary[['salary17_18','Pos','MPG','PPG','APG',
'RPG','TOPG','BPG','SPG','Age','PER']]
dfData = heat_salary.corr() #相关矩阵
sns.heatmap(dfData).set(
xlabel='变量',
ylabel='变量')
相关性系数在0-1之间浮动变化。图中格子的颜色越浅,说明变量的相关性越强。我们可以看出和薪资变量相关性较大的是场均得分、出场时间和效率值等变量,而较为不重要的因素是年龄和场均封盖。这可能是因为年龄较大的球员可能直接选择退役或被球队裁掉,而不是继续待在球队中拿底薪。值得注意的是,场均失误数和场均得分、场均助攻相关性较强,这说明参与进攻越多的球员同时也会导致更多的失误。
以上我们将NBA球员的技术统计和薪资数据做了一些清理和分析,明天我们将使用随机森林算法对薪资进行预测。敬请期待~
关于我们
微信公众号“Stata and Python数据分析”分享实用的stata、python等软件的数据处理知识,欢迎转载、打赏。我们是由李春涛教授领导下的研究生及本科生组成的大数据处理和分析团队。
1)必须原创,禁止抄袭;
2)必须准确,详细,有例子,有截图;
注意事项:
1)所有投稿都会经过本公众号运营团队成员的审核,审核通过才可录用,一经录用,会在该推文里为作者署名,并有赏金分成。
2)邮件请注明投稿,邮件名称为“投稿+推文名称”。
3)应广大读者要求,现开通有偿问答服务,如果大家遇到有关数据处理、分析等问题,可以在公众号中提出,只需支付少量赏金,我们会在后期的推文里给予解答。